﻿using Cinemachine;
using MyUtil;
using TMPro;
using Unity.Netcode;
using Unity.Netcode.Components;
using UnityEngine;

public class Knight : NetworkBehaviour
{
    public static Knight Instance;
    Animator animator;
    NetworkAnimator networkAnimator;
    new Rigidbody2D rigidbody;
    SpriteRenderer spriteRenderer;    

    [SerializeField] KnightData KnightData;
    [SerializeField] KnightData data;
    float currentSpeed;

    [SerializeField] int currentHealth=5;

    [Header("Timer")]
    Timer invincibleTimer;
    bool isInvincible = false;
    
    Timer rollCdTimer;
    bool canRoll = true;

    float horizontal,
        vertical;

    bool facingLeft = false;

    public int Health { get { return currentHealth; } set { MyEvenSystem.OnPlayerHealthChanged.Invoke(value-currentHealth); currentHealth = value;  } }
    public int Damage { get { return data.Damage; } set { data.Damage = value; } }
    public int Money { get { return data.Money; } set { data.Money = value; MyEvenSystem.OnPlayerMoneyChanged.Invoke(data.Money); } }
    public Vector2 Center =>spriteRenderer.bounds.center;

    private void Awake()
    {
        //在Awake中赋值，以便Center的使用
        spriteRenderer = GetComponentInChildren<SpriteRenderer>();
    }

    void Start()
    {        
        animator = GetComponent<Animator>();
        networkAnimator = GetComponent<NetworkAnimator>();
        rigidbody = GetComponent<Rigidbody2D>();                
    }

    public override void OnNetworkSpawn()
    {
        if (!IsOwner)
            return;
        
        Instance= this;
        data = Instantiate(KnightData);        
        currentSpeed = data.IdleSpeed;
        currentHealth = (int)data.MaxHealth;

        transform.position= Random.insideUnitCircle * 2;
        invincibleTimer = TimerManager.Instance.CreateTimer(data.InvincibleCd, OnInvincibleTimerTimeout, true);
        rollCdTimer = TimerManager.Instance.CreateTimer(data.RollCd, OnRollCdTimeout, true);
    }

    public override void OnNetworkDespawn()
    {
        if(!IsOwner) return;

        TimerManager.Instance.RemoveTimer(invincibleTimer);
        TimerManager.Instance.RemoveTimer(rollCdTimer);
    }

    // Update is called once per frame
    void Update()
    {
        if (!IsOwner)
            return;

        horizontal = Input.GetAxis("Horizontal");
        vertical = Input.GetAxis("Vertical");

        if (Input.GetKeyDown(KeyCode.Space) && canRoll)
            OnRoll();
    }

    private void FixedUpdate()
    {
        if (!IsOwner) return;

        Vector2 velocity = new(horizontal, vertical);
        animator.SetFloat("Velocity", velocity.normalized.magnitude);

        if (horizontal > 0)
            facingLeft = false;
        else if (horizontal < 0)
            facingLeft = true;

        if (facingLeft)
           spriteRenderer.transform.localScale = new Vector2(-1, 1);
        else
            spriteRenderer.transform.localScale = new Vector2(1, 1);

        rigidbody.MovePosition(rigidbody.position + currentSpeed * Time.fixedDeltaTime * velocity.normalized);
    }  
    
    void OnRoll()
    {
        isInvincible = true;
        canRoll = false;
        currentSpeed = data.RollSpeed;
        rollCdTimer.Start();
        networkAnimator.SetTrigger("OnRoll");
    }

    //翻滚动画结束时通过AnimationEvent调用，仅拥有者调用
    void OnRollInvincibleEnd()
    {        
        if (!IsOwner) return;
        currentSpeed = data.IdleSpeed;
        isInvincible = false;
    }

    void OnRollCdTimeout()
    {
        canRoll = true;
    }

    public void OnHit(int damage)
    {                
        HitRpc(damage);
    }

    [Rpc(SendTo.Owner)]
    void HitRpc(int damage)
    {
        if (isInvincible)
            return;

        isInvincible = true;
        invincibleTimer.Start();
        Health = Mathf.Clamp(Health - damage, 0, int.MaxValue);
        networkAnimator.SetTrigger("OnHit");

        if (currentHealth <= 0)
            OnDead();
    }

    void OnDead()
    {
        networkAnimator.SetTrigger("OnDead");
    }

    void OnDeadAnimaFinish()
    {
        if (!IsOwner) return;
        SendDeathRpc(OwnerClientId);
    }

    //通知所有客户端该玩家gg
    [Rpc(SendTo.ClientsAndHost)]
    void SendDeathRpc(ulong clientId)
    {
        //主机判断游戏是否结束
        if (IsHost)
        {            
            if (GameManager.Instance.IsSinglePlay)
            {
                GameManager.Instance.GameOver();
            }
            else
            {
                bool isAllDead = true;                
                for(int i=0;i< MultiPlayManager.Instance.Players.Count;i++)
                {
                    var player = MultiPlayManager.Instance.Players[i];                    
                    if (player.id == clientId)
                    {
                        var newData = player;
                        newData.isLive = false;
                        MultiPlayManager.Instance.Players[i] = newData;
                    }
                    else if (player.isLive)
                    {
                        isAllDead = false;
                    }
                }
                if (isAllDead)
                {
                    ResetLiveState();
                    GameManager.Instance.GameOver();
                }
            }
        }
        gameObject.SetActive(false);
        LevelManager.Instance.TrySetVCamFollow(transform);        
    }

    //重置当前客户端的玩家状态，仅拥有者调用
    public void ResetState()
    {
        if (IsHost)
        {
            ResetLiveState();
        }

        Health = (int)data.MaxHealth;
        
        for(int i = 0; i < transform.parent.childCount; i++)
        {
            var child = transform.parent.GetChild(i);
            child.gameObject.SetActive(true);
        }
    }
    
    void ResetLiveState()
    {
        for (int i = 0; i < MultiPlayManager.Instance.Players.Count; i++)
        {
            var player = MultiPlayManager.Instance.Players[i];
            var newData = player;
            newData.isLive = true;
            MultiPlayManager.Instance.Players[i] = newData;
        }
    }

    void OnInvincibleTimerTimeout()
    {        
        isInvincible = false;
    }
}
